Skip to content

feat: auto-generate session titles via the managed chat_title tool - #2351

Merged
liruifengv merged 63 commits into
mainfrom
auto-title
Aug 13, 2026
Merged

feat: auto-generate session titles via the managed chat_title tool#2351
liruifengv merged 63 commits into
mainfrom
auto-title

Conversation

@7Sageer

@7Sageer 7Sageer commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

No linked issue — the problem is explained below.

Problem

Session titles are initially derived by truncating the first user prompt to 200 characters. Long or pasted prompts produce unreadable sidebar titles, while the managed platform already exposes a chat_title tool that can generate a concise title from conversation content. The server stack had no reusable on-demand path for calling that tool and persisting the result.

What changed

Adds automatic session title generation for agent-core-v2 sessions authenticated through the managed Kimi Code OAuth provider. As soon as the engine accepts a prompt, the TUI asks it to generate a title from the conversation's first prompts, retrying after each main-agent turn ends until one is applied; a title is generated at most once per session unless explicitly regenerated. This takes effect only on the v2 engine: the default v1 CLI keeps prompt-derived titles, and kimi web does not trigger generation yet.

Generation requires a managed OAuth login and otherwise leaves the current title untouched. For logged-in users, up to the first three natural-language user prompts (each prefixed with a plain user: role marker, capped at 1000 characters combined) are sent to the managed /tools chat_title endpoint — this applies to sessions on any model provider, consistent with the other managed tools (web search, fetch-url). Sessions without a managed login are unaffected.

  • oauth: add fetchChatTitle for the managed platform /tools chat_title method, including authoritative protocol headers, an 8-second timeout, response validation, and structured failures.
  • agent-core-v2: add the Session-scoped ISessionTitleService and Agent-scoped prompt source. The service coalesces concurrent requests, caps generated titles at 200 characters, retries once with a force-refreshed token on a 401, and drops the write-back when the session scope was closed or superseded mid-flight. Persisted metadata records the title source (prompt / generated / custom): a custom title is never overwritten, and an already-generated title is not regenerated unless forced.
  • kap-server: POST /api/v1/sessions/{session_id}/title/generate accepts an optional { "force": true } body to regenerate an already-generated title. Unknown sessions return 40401; unavailable generation returns 40922.
  • node-sdk / klient: plumb the force option through the public facade; fix session.meta.updated patches without lastPrompt being dropped by klient event validation; emit exactly one metadata event per applied title; the temporary resume→act→close paths (generateSessionTitle, renameSession) no longer close a session that a concurrent public resume has handed out.
  • TUI: request title generation as soon as a prompt is accepted, retrying after each main-agent turn ends until one succeeds and disabling on hard failures.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added unit and integration coverage for the managed request contract, prompt selection, title-source persistence and races, 401 refresh, the stale-scope guard, event validation, and the public REST path.
  • Ran gen-changesets skill; .changeset/auto-session-title.md announces the automatic title as a minor CLI entry.
  • Ran gen-docs skill; no user documentation update is needed until a shipped surface exposes this behavior.

With the auto-title experimental flag on and a managed OAuth login, the
session title is generated from the first prompt, replacing the
truncated-prompt easy title. A custom title set by the user is never
overwritten, and generation failures degrade silently to the easy title.

- oauth: fetchChatTitle for the platform /tools chat_title method
- agent-core (v1): fire-and-forget generation on the first prompt
- agent-core-v2: sessionTitle domain watching the easy-title event
- kap-server: POST /sessions/{id}/title/generate for manual regeneration
@changeset-bot

changeset-bot Bot commented Jul 29, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e2a7e5c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 8 packages
Name Type
@moonshot-ai/agent-core-v2 Minor
@moonshot-ai/kimi-code-sdk Minor
@moonshot-ai/kap-server Patch
@moonshot-ai/klient Patch
@moonshot-ai/kimi-code-oauth Patch
@moonshot-ai/acp-server Patch
@moonshot-ai/acp-adapter Patch
kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

7Sageer added 6 commits July 29, 2026 16:15
Drop the automatic wiring on both engines: the v1 (TUI) first-prompt
trigger and the v2 easy-title event watcher. SessionTitleService's
generateTitle() stays as the single on-demand entry point behind the
auto-title flag, backing the kap-server title/generate route. The
changeset goes away too: with no shipped consumer, the remaining
surface is not user-perceivable.
@pkg-pr-new

pkg-pr-new Bot commented Jul 29, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@e2a7e5c
npx https://pkg.pr.new/@moonshot-ai/kimi-code@e2a7e5c

commit: e2a7e5c

7Sageer added 21 commits July 30, 2026 12:10
Record up to three sanitized natural-language prompts in session
metadata (skill / plugin activations excluded) and compose the
chat_title input as order-labeled lines truncated to a 1000-char
budget, falling back to lastPrompt for sessions without recorded
prompts.
# Conflicts:
#	packages/agent-core-v2/test/session/sessionMetadata/sessionMetadata.test.ts
- persist titleSource (prompt/generated/custom); skip auto-generation over
  an already-generated title unless forced, and never over a custom one
- plumb the force option from the core through klient and node-sdk to the
  REST title/generate endpoint
- drop the title write-back when the session scope was superseded
  mid-flight, and retry once with a force-refreshed token on a 401
- stop closing sessions a concurrent public resume has handed out in the
  temporary resume paths (generateSessionTitle, renameSession)
- accept session.meta.updated patches without lastPrompt in klient event
  validation, and emit exactly one metadata event per applied title
- remove the retired prompts field heal and drop the changeset (the
  behavior is only perceivable on the experimental v2 engine)
# Conflicts:
#	packages/agent-core-v2/docs/state-manifest.d.ts
#	packages/agent-core-v2/test/workspace/workspaceHandler/workspaceHandler.test.ts
#	packages/node-sdk/src/sdk-rpc-client-v2.ts
…dler

The session title service must not depend on the Workspace-tier handler
registry. The handler now seeds each session scope with an abort signal,
fires it synchronously when a close begins, and the title service carries
the signal on its request, drops the write-back once aborted, and drains
an in-flight generation through the onWillCloseSession hook.
A v1 rename spreads the original state.json document, so an explicit
isCustomTitle: true can travel with a stale titleKind. The explicit
marker now wins on load, and every persist double-writes the derived
isCustomTitle so released v1 builds keep recognizing the custom title.
The temporary resume/rename/close paths and the public lifecycle
operations now share a per-session queue, so a public resume can never
receive a handle whose cleanup close is already in flight. Session
summaries carry the canonical title state, letting the TUI skip title
generation for sessions whose title was already generated or customized
instead of re-asking after every turn.
A close/archive is now tracked in a closing registry from its first
synchronous step until disposal: get/list hide the closing session and
resume waits the close out instead of returning the doomed handle, and
fork waits out an in-flight source close. The title service tracks the
whole generateTitle call as the unit the close hook drains, and the
generated-title write re-checks the lifetime signal inside the serialized
metadata update so an abort landing while the update is queued still
vetoes the write-back.
readSummary and the read-model mirror carry titleKind, so listSessions
reports the same canonical title state as a resumed session's summary.
7Sageer and others added 16 commits July 31, 2026 15:37
Nothing calls force: with it gone, plain calls always coalesce onto the
shared in-flight generation, so the generation sequence and the
caller-supplied allowWhen veto lose their only purpose and go with it.
The title/generate REST route takes no body anymore.
…sion index

The listed-session titleKind had no consumer: the TUI's title-generation
gate seeds from the resumed summary, which reads the live metadata
document, and the kap-server REST wire never carried the field. Removing
the projection also retires the read-model summary version stamp (the
remaining shape is fully field-checkable) and the duplicate title-kind
derivation that had to stay in lockstep with sessionMetadata. The klient
list contract and the node-sdk list mapper drop the field with it; the
resumed/live summary still reports the canonical title state.
…essageLegacy

mergeContextTranscriptWithLive had a single caller; move the logic into
messageLegacyService as the private mergeLiveTail and drop the export.
# Conflicts:
#	packages/agent-core-v2/docs/state-manifest.d.ts
#	packages/agent-core-v2/scripts/check-domain-layers.mjs
#	packages/agent-core-v2/src/session/sessionMetadata/sessionMetadataService.ts
#	packages/agent-core-v2/src/workspace/sessionLifecycle/sessionLifecycleService.ts
#	packages/node-sdk/src/sdk-rpc-client-v2.ts
…ifecycle

Auto title no longer consumes close-awareness, so the machinery goes
back to the simple forms: close/archive run straight through, resume
no longer waits out an in-flight close, create/fork drop their target
reservation, and a cold archive is a no-op again. Reverts the behavior
of e7c397a and cd1cea0 on top of the sessionLifecycle rename.
Signed-off-by: 7Sageer <sag77r@hotmail.com>
…title test

The main merge reduced #/kosong/model/hostRequestHeaders to the pure
port contract; define the test's headers as a plain value matching it
and tidy the SDK test import grouping.
Keep the capability only: the engine-side title generation service, the
POST /sessions/{id}/title/generate route, and the SDK generateSessionTitle
method stay; the TUI no longer requests a title on prompt accept or on
session attach. The changeset now covers the SDK capability instead of a
CLI-facing auto title.
Signed-off-by: 7Sageer <sag77r@hotmail.com>
ISessionTitleService.generateTitle and the metadata write-back take an
optional force flag that bypasses the custom/generated guards, so an
explicit user request (the desktop/web rename field's Gen Title action)
can overwrite any current title; the applied title is marked generated.
Forced calls skip the in-flight coalescing, and a forced write is plain
last-writer-wins.

kap-server's POST /sessions/{id}/title/generate accepts an optional
{ "force": true } body; klient and the node-sdk plumb the option through
(GenerateSessionTitleInput.force).

Also renumber SESSION_TITLE_UNAVAILABLE to 40923: main assigned 40922 to
PAGE_TOKEN_MISMATCH after this branch forked.
…ation

generateTitle gains a source option alongside force:

- user_prompts (default): the existing first-prompts window, unchanged.
- first_turn: the opening user prompt paired with the first turn's final
  assistant text — strict, so a caller asking before the first reply lands
  simply gets unavailable and can retry at the next turn boundary.
- digest: first prompt + latest prompt + the latest turn's final assistant
  text, tolerating a compacted window by using whatever segments survive;
  meant for explicit regeneration on multi-turn sessions.

Assistant segments keep only natural-language text parts (tool calls,
thinking, and media never contribute) and pass through the shared metadata
sanitizer, which redacts secrets and long base64-looking runs; each
segment is capped (user 300, assistant 600/400) so the composed
chat_content stays within the 1000-char budget. The kap-server route,
klient contract, and node-sdk plumb the option through. Excerpt extraction
is covered against the real context memory (loop-event folding), and the
REST surface gains a digest composition case.
# Conflicts:
#	packages/agent-core-v2/src/agent/rpc/prompt-metadata.ts
#	packages/agent-core-v2/src/index.ts
#	packages/agent-core-v2/src/session/sessionMetadata/sessionMetadataService.ts
#	packages/agent-core-v2/src/workspace/sessionLifecycle/sessionLifecycleService.ts
#	packages/agent-core-v2/test/agent/prompt/promptMetadataText.test.ts
#	packages/agent-core-v2/test/app/sessionIndex/sessionIndex.test.ts
#	packages/agent-core-v2/test/workspace/sessionLifecycle/sessionLifecycle.test.ts
#	packages/kap-server/src/protocol/error-codes.ts
#	packages/kap-server/src/routes/sessions.ts
#	packages/klient/src/contract/index.ts
#	packages/klient/src/transports/memory/serviceRegistry.ts
#	packages/klient/test/contract-parity.ts
#	packages/node-sdk/src/sdk-rpc-client-v2.ts
#	packages/node-sdk/test/sdk-rpc-client-v2.test.ts
#	packages/node-sdk/test/v1-v2-parity.test.ts
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

❌ Nix build failed

    kimi-code>       │                                 ╰── Opened here
    kimi-code>       │
    kimi-code>  1377 │     } else if ((await this.engineAccessor.get(ISessionIndex).get(sessionId)) === undefined) {
    kimi-code>       │       ──┬─
    kimi-code>       │         ╰─── `,` or `)` expected
    kimi-code> ──────╯
    kimi-code> 
    kimi-code>     at aggregateBindingErrorsIntoJsError (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/error-CkdMJ9ps.mjs:48:18)
    kimi-code>     at unwrapBindingResult (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/error-CkdMJ9ps.mjs:18:128)
    kimi-code>     at #build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/rolldown-build-BVD3dIdE.mjs:3275:34)
    kimi-code>     at async build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/index.mjs:42:22)
    kimi-code>     at async Promise.all (index 0)
    kimi-code>     at async buildSingle (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/build-5FURNVr0.mjs:765:19)
    kimi-code>     at async Promise.all (index 0)
    kimi-code>     at async buildWithConfigs (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/build-5FURNVr0.mjs:721:18)
    kimi-code>     at async CAC.<anonymous> (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/run.mjs:22:2)
    kimi-code>     at async runCLI (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/run.mjs:46:3)
    kimi-code> Command failed: /nix/store/chsxa1iw7s3m51v4kj43yd1nw26xvi21-nodejs-24.15.0/bin/node /build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/run.mjs --config tsdown.native.config.ts
    kimi-code> 
    kimi-code>  ERROR  Error: Build failed with 1 error:
    kimi-code> 
    kimi-code> [PARSE_ERROR] Expected `,` or `)` but found `else`
    kimi-code>       ╭─[ ../../packages/node-sdk/src/sdk-rpc-client-v2.ts:1377:7 ]
    kimi-code>       │
    kimi-code>  1362 │     return this.runSessionAccess(sessionId, async () => {
    kimi-code>       │                                 ┬
    kimi-code>       │                                 ╰── Opened here
    kimi-code>       │
    kimi-code>  1377 │     } else if ((await this.engineAccessor.get(ISessionIndex).get(sessionId)) === undefined) {
    kimi-code>       │       ──┬─
    kimi-code>       │         ╰─── `,` or `)` expected
    kimi-code> ──────╯
    kimi-code> 
    kimi-code>     at aggregateBindingErrorsIntoJsError (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/error-CkdMJ9ps.mjs:48:18)
    kimi-code>     at unwrapBindingResult (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/error-CkdMJ9ps.mjs:18:128)
    kimi-code>     at #build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/rolldown-build-BVD3dIdE.mjs:3275:34)
    kimi-code>     at async build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/index.mjs:42:22)
    kimi-code>     at async Promise.all (index 0)
    kimi-code>     at async buildSingle (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/build-5FURNVr0.mjs:765:19)
    kimi-code>     at async Promise.all (index 0)
    kimi-code>     at async buildWithConfigs (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/build-5FURNVr0.mjs:721:18)
    kimi-code>     at async CAC.<anonymous> (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/run.mjs:22:2)
    kimi-code>     at async runCLI (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/run.mjs:46:3)
    kimi-code> 
    kimi-code> 
    kimi-code> /build/source/apps/kimi-code:
    kimi-code>  ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  @moonshot-ai/kimi-code@0.36.0 build:native:sea: `node scripts/native/build.mjs --profile=local`
    kimi-code> Exit status 1
    error: Cannot build '/nix/store/cgial0zgb3yx1dgz25ng2lcmqsn6ag4j-kimi-code-0.36.0.drv'.
           Reason: builder failed with exit code 1.
           Output paths:
             /nix/store/am89lmxcfc8y62hlzr9a7ky43gllfnm5-kimi-code-0.36.0
           Last 25 log lines:
           >       │
           >  1362 │     return this.runSessionAccess(sessionId, async () => {
           >       │                                 ┬
           >       │                                 ╰── Opened here
           >       │
           >  1377 │     } else if ((await this.engineAccessor.get(ISessionIndex).get(sessionId)) === undefined) {
           >       │       ──┬─
           >       │         ╰─── `,` or `)` expected
           > ──────╯
           >
           >     at aggregateBindingErrorsIntoJsError (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/error-CkdMJ9ps.mjs:48:18)
           >     at unwrapBindingResult (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/error-CkdMJ9ps.mjs:18:128)
           >     at #build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/rolldown-build-BVD3dIdE.mjs:3275:34)
           >     at async build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/index.mjs:42:22)
           >     at async Promise.all (index 0)
           >     at async buildSingle (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/build-5FURNVr0.mjs:765:19)
           >     at async Promise.all (index 0)
           >     at async buildWithConfigs (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/build-5FURNVr0.mjs:721:18)
           >     at async CAC.<anonymous> (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/run.mjs:22:2)
           >     at async runCLI (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__e3c4b77bdbb7c42f8dbfce92959948a8/node_modules/tsdown/dist/run.mjs:46:3)
           >
           >
           > /build/source/apps/kimi-code:
           >  ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  @moonshot-ai/kimi-code@0.36.0 build:native:sea: `node scripts/native/build.mjs --profile=local`
           > Exit status 1
           For full logs, run:
             nix log /nix/store/cgial0zgb3yx1dgz25ng2lcmqsn6ag4j-kimi-code-0.36.0.drv

…ntal flag

Registers the  flag (off by default; env
KIMI_CODE_EXPERIMENTAL_SESSION_TITLE, the master flag, or the
[experimental] config section) and makes generateTitle report
unavailable while it is off, so every entry point — the kap-server
route, klient, node-sdk, and through them the clients' auto trigger and
rename-field action — is inert unless the user opts in.
Snake-case id matching search_worker / persistence_minidb_readmodel; env
KIMI_CODE_EXPERIMENTAL_AUTO_SESSION_TITLE.
The main-merge commit captured pre-fix snapshots of four files; the
actual resolutions only lived in my working tree: the LifecycleScope
import move to #/app/scopes, the titleKind port of
applyPromptMetadataUpdate, the Promise<void> pinning of the metadata
update queue, and the reloadSession runSessionAccess closure.
Generation now reports unavailable with the flag off, so the two
title-generation harnesses opt in through the written config's
[experimental] section.
@liruifengv
liruifengv merged commit 6be2697 into main Aug 13, 2026
14 checks passed
@liruifengv
liruifengv deleted the auto-title branch August 13, 2026 09:59
@github-actions github-actions Bot mentioned this pull request Aug 13, 2026
mohidmakhdoomi added a commit to mohidmakhdoomi/kimi-code that referenced this pull request Aug 13, 2026
Two files conflicted, both where main rewrote a region this branch also
touches:

- packages/node-sdk/src/sdk-rpc-client-v2.ts — the engine import block, where
  MoonshotAI#2871 replaced the agent RPC aggregation layer with
  IAgentPluginCommandService and MoonshotAI#2700 removed IModelCatalog along with the
  secondary-model machinery. Main's removals are kept and this branch's
  additions re-applied on top of them; no removed service is resurrected.
- docs/zh/reference/kimi-command.md — main unified the locale on "main agent"
  and "subagent", so the --agent-file paragraph this branch adds is restated
  in that terminology.

One comment was rewritten rather than merged as-is. The rollback in
createSession justified its handle-identity check with the
SESSION_ALREADY_EXISTS check not being atomic, which MoonshotAI#2351 has since made
false: an explicit id now runs the whole create behind a per-session queue.
The check itself stays, because the engine's create still registers its handle
without a duplicate-id guard of its own, but it is now described as what keeps
a rollback from taking a session the call did not create.

The claims the rest of the change rests on were re-verified against the merged
tree: session creation still awaits the same five workspace profile loaders,
still announces the finished session as its last step, and MoonshotAI#2896's move of the
session lifecycle hooks onto lifecycle events leaves SessionStart and
SessionEnd firing from create and close as before.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants